package com.seleniti.enpareja.controller.ui.base;

import org.ioc.commons.flowcontrol.actioncontroller.ActionController;
import org.ioc.commons.flowcontrol.actioncontroller.IsExternalAction;
import org.ioc.commons.flowcontrol.eventbus.EventBus;
import org.ioc.commons.flowcontrol.eventbus.IsEvent;
import org.ioc.commons.flowcontrol.logincontroller.LoginController;
import org.ioc.commons.flowcontrol.messageboxfactory.MessageBoxFactory;
import org.ioc.commons.flowcontrol.notificator.Notificator;
import org.ioc.commons.flowcontrol.operationmanager.IsOperation;
import org.ioc.commons.flowcontrol.operationmanager.OperationManager;
import org.ioc.commons.flowcontrol.placecontroller.PlaceController;
import org.ioc.commons.flowcontrol.taskcontroller.TaskController;
import org.ioc.commons.i18n.DateTimeFormatter;
import org.ioc.commons.integration.dataaccess.localstorage.LocalClientStorage;
import org.ioc.commons.model.globaldata.GlobalDataController;
import org.ioc.commons.ui.HasDisplay;
import org.ioc.commons.ui.IsDisplay;
import org.ioc.commons.ui.IsPresenter;

import com.seleniti.enpareja.controller.common.GlobalData;
import com.seleniti.enpareja.controller.common.LocalData;
import com.seleniti.enpareja.controller.common.domain.LoggedUserInfo;
import com.seleniti.enpareja.controller.control.controller.LoginFailedCause;
import com.seleniti.enpareja.controller.control.controller.LoginParams;
import com.seleniti.enpareja.controller.control.factory.ClientFactory;
import com.seleniti.enpareja.controller.control.factory.ClientFactory.NotificationIcons;
import com.seleniti.enpareja.controller.control.factory.EnParejaExceptionController;
import com.seleniti.enpareja.controller.model.integration.service.EnParejaServiceManager;

public abstract class EnParejaBasePresenter<D extends IsDisplay<E, O, A>, E extends Enum<? extends IsEvent>, O extends Enum<? extends IsOperation>, A extends Enum<? extends IsExternalAction>>
		implements IsPresenter, HasDisplay<D, E, O, A> {
	protected static ClientFactory clientFactory;

	public static ClientFactory getClientFactory() {
		return clientFactory;
	}

	public static void setClientFactory(ClientFactory clientFactory) {
		EnParejaBasePresenter.clientFactory = clientFactory;
	}

	protected final D display;
	protected final EventBus<E> eventbus;
	protected final OperationManager<O> operationManager;
	protected final ActionController<A> actionController;

	protected PlaceController placeController;

	protected EnParejaExceptionController exceptionController;

	protected TaskController taskController;
	protected Notificator<NotificationIcons> notificator;

	protected MessageBoxFactory messageBoxFactory;

	/**
	 * Services
	 */
	protected GlobalDataController<GlobalData> globalDataController;
	protected EnParejaServiceManager serviceManager;
	protected DateTimeFormatter dateTimeFormatter;
	protected LoginController<LoggedUserInfo, LoginFailedCause, LoginParams, String> loginController;
	protected LocalClientStorage<LocalData> localClientStorage;

	protected EnParejaBasePresenter(D display, EventBus<E> eventbus, OperationManager<O> operationManager,
			ActionController<A> actionController) {
		assert (clientFactory != null) : "Presenters derived from " + EnParejaBasePresenter.class
				+ " must be assigned to a ClientFactory before being used";

		this.display = display;
		this.eventbus = eventbus;
		this.operationManager = operationManager;
		this.actionController = actionController;

		this.globalDataController = clientFactory.getGlobalDataController();
		this.localClientStorage = clientFactory.getLocalClientStorage();
		this.dateTimeFormatter = clientFactory.getDateTimeFormatter();
	}

	@Override
	public void onInitDisplay() {
		this.placeController = clientFactory.getPlaceController().forThisObject(this);
		this.exceptionController = clientFactory.getExceptionController();
		this.taskController = clientFactory.getTaskController().forThisObject(this);
		this.notificator = clientFactory.getNotificator().forThisObject(this);

		/**
		 * Connection with the engine services
		 */
		this.serviceManager = clientFactory.getServiceManager();

		this.messageBoxFactory = clientFactory.getMessageBoxFactory().forThisObject(this);
		this.loginController = clientFactory.getLoginController();
	}

	@Override
	public D getDisplay() {
		return this.display;
	}

}
